package cn.sumpu.app.guoguojie.biz.impl;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import cn.sumpu.app.guoguojie.biz.ImageBiz;
import cn.sumpu.app.guoguojie.domain.Member;
import cn.sumpu.app.guoguojie.domain.Ext.ImageWeb;
import cn.sumpu.app.guoguojie.exception.AppBusinessException;
import cn.sumpu.app.guoguojie.util.Common;
import cn.sumpu.app.guoguojie.util.HttpProxy;
import cn.sumpu.app.guoguojie.util.ImageUtil;

public class ImageBizImpl implements ImageBiz {

	private final static Logger logger = LoggerFactory
			.getLogger(ImageBizImpl.class);

	private String uploadPath;
	private String imageServer;
	private String imageDir;

	public void setUploadPath(String uploadPath) {
		this.uploadPath = uploadPath;
	}

	public String getImageServer() {
		return imageServer;
	}

	public void setImageServer(String imageServer) {
		this.imageServer = imageServer;
	}

	public void setImageDir(String imageDir) {
		this.imageDir = imageDir;
	}

	/**
	 * @param srcImgPath
	 *            要被切割的图像地址
	 * @param descDir
	 *            要保存图像的地址,如果是保存到服务器则是服务器的地址
	 * @param imageName
	 *            保存图片的名称
	 * @param x
	 *            要切割的图片的在原图片的x坐标
	 * @param y
	 *            要切割的图片的在原图片的y坐标
	 * @param destWidth
	 *            要切割图片的宽度
	 * @param destHeight
	 *            要切割图片的高度
	 * @param divWidth
	 *            要切割图片的分辨率的宽度
	 * @param divHeight
	 *            客户端原图片外层的高度
	 * @param tagWidth
	 *            要切割图片的分辨率的宽度
	 * @param tagHeight
	 *            要切割图片的分表率的高度
	 * @param uploadServer
	 *            是否上传到图片服务器
	 * @return
	 * @throws AppBusinessException
	 */
	@Override
	public String cutAvatar(String srcImgPath, String descDir,
			String imageName, int x, int y, int destWidth, int destHeight,
			int divWidth, int divHeight, int tagWidth, int tagHeight,
			boolean uploadServer) throws AppBusinessException {
		try {

			Image img;
			ImageFilter cropFilter;
			BufferedImage bi = ImageIO.read(new File(srcImgPath));
			int srcWidth = bi.getWidth();
			int srcHeight = bi.getHeight();

			double zoom = (double) srcWidth / divWidth;
			double zoomHeight = (double) srcHeight / divHeight;
			if (zoomHeight > zoom) {
				zoom = zoomHeight;
			}
			if (destWidth == 0 || destHeight == 0) {
				destWidth = divWidth;
				destHeight = divHeight;
			}
			int tmpTagWidth = (int) (destWidth * zoom);
			int tmpTagHeight = (int) (destHeight * zoom);
			if (tmpTagWidth < tagWidth && tmpTagHeight < tagHeight) {
				tagWidth = tmpTagWidth;
				tagHeight = tmpTagHeight;
			}
			cropFilter = new CropImageFilter((int) (x * zoom),
					(int) (y * zoom), (int) (destWidth * zoom),
					(int) (destHeight * zoom));
			img = Toolkit.getDefaultToolkit().createImage(
					new FilteredImageSource(bi.getSource(), cropFilter));

			BufferedImage tag = new BufferedImage(tagWidth, tagWidth,
					BufferedImage.TYPE_INT_RGB);
			Graphics g = tag.getGraphics();
			g.drawImage(img, 0, 0, tagWidth, tagWidth, null);
			g.dispose();
			File f = new File(descDir);
			if (!f.exists()) {
				f.mkdirs();
			}
			if (uploadServer) {
				String serverUrl = imageServer + "receiveImage.ajax";
				ByteArrayOutputStream bao_org = new ByteArrayOutputStream();
				ImageIO.write(tag, "jpg", bao_org);
				requestSaveImage(serverUrl, descDir, imageName,
						bao_org.toByteArray());
				return imageServer;
			} else {
				ImageIO.write(tag, "JPEG", new File(descDir + imageName
						+ ".jpg"));
				return "";
			}

		} catch (Exception e) {
			e.printStackTrace();
			throw new AppBusinessException("切割头像失败", e);
		}
	}

	@Override
	public String makeThumbnail(String srcImgPath, Map<String, Object> settings)
			throws AppBusinessException {
		return ImageUtil.makeThumbnail(srcImgPath, settings);
	}

	@Override
	public void makeWatermark(String waterText, String targetImg, Font font,
			Color color, int watermarkPos) throws AppBusinessException {
		ImageUtil
				.makeWatermark(waterText, targetImg, font, color, watermarkPos);
	}

	@Override
	public void makeWatermark(String waterImg, String targetImg,
			int watermarkPos) throws AppBusinessException {
		ImageUtil.makeWatermark(waterImg, targetImg, watermarkPos);
	}

	@Override
	public String makeThumbnail(String srcImgPath, int thumbnailWidth,
			int thumbnailHeight, int maxThumbnailWidth, int maxThumbnailHeight)
			throws AppBusinessException {
		return ImageUtil.makeThumbnail(srcImgPath, thumbnailWidth,
				thumbnailHeight, maxThumbnailWidth, maxThumbnailHeight);
	}

	@Override
	public boolean checkUploadSize(HttpServletRequest request)
			throws AppBusinessException {
		try {
			MultipartHttpServletRequest re = (MultipartHttpServletRequest) request;
			Map<String, MultipartFile> map = re.getFileMap();
			List<MultipartFile> fileList = new ArrayList<MultipartFile>();
			for (Object obj : map.values()) {
				MultipartFile file = (MultipartFile) obj;
				fileList.add(file);
			}
			if (fileList.size() > 0) {
				MultipartFile fj = fileList.get(0);
				if (fj.getSize() > Common.PHOTO_SIZE_ALLOW) {
					return false;
				} else
					return true;
			}
			return false;
		} catch (Exception e) {
			e.printStackTrace();
			throw new AppBusinessException("check upplad size failure!", e);
		}

	}

	@Override
	public void upload(HttpServletRequest request) throws AppBusinessException {
		MultipartHttpServletRequest re = (MultipartHttpServletRequest) request;
		Map<String, MultipartFile> map = re.getFileMap();
		List<MultipartFile> fileList = new ArrayList<MultipartFile>();
		for (Object obj : map.values()) {
			MultipartFile file = (MultipartFile) obj;
			fileList.add(file);
		}
		if (fileList.size() > 0) {
			String webAppPath = request.getSession().getServletContext()
					.getRealPath("/");
			Member member = (Member) request.getSession()
					.getAttribute("member");
			String family = member.getFamily();
			String formateDate = Common.getFormatDate(new Date());
			String tmpPath = webAppPath + File.separator + "tmp"
					+ File.separator + "pic" + File.separator + formateDate
					+ File.separator + family;
			File uploadfujian = new File(tmpPath);
			if (!uploadfujian.exists()) {
				uploadfujian.mkdirs();
			}
			for (int i = 0; i < fileList.size(); i++) {
				MultipartFile fj = fileList.get(i);
				String fn = fj.getOriginalFilename();
				if (null != fn && fn.length() > 0) {
					String uuid = UUID.randomUUID().toString();
					String fujianpath = uploadfujian + File.separator + uuid
							+ ".jpg";
					try {
						InputStream buffin = new ByteArrayInputStream(
								fj.getBytes());
						BufferedImage bi = ImageIO.read(buffin);

						ImageIO.write(bi, "JPG", new File(fujianpath));

					} catch (IOException e) {
						e.printStackTrace();
						throw new AppBusinessException("upload fail", e);
					}
				}
			}
		}
	}

	@Override
	public ImageWeb uploadOneImg(HttpServletRequest request)
			throws AppBusinessException {
		try {
			ImageWeb imageWeb = new ImageWeb();
			MultipartHttpServletRequest re = (MultipartHttpServletRequest) request;
			Map<String, MultipartFile> map = re.getFileMap();
			List<MultipartFile> fileList = new ArrayList<MultipartFile>();
			Member member = (Member) request.getSession()
					.getAttribute("member");
			for (Object obj : map.values()) {
				MultipartFile file = (MultipartFile) obj;
				fileList.add(file);
			}
			if (fileList.size() > 0) {
				String tmpPath = request.getSession().getServletContext()
						.getRealPath("/")
						+ File.separator + uploadPath;
				File uploadfujian = new File(tmpPath);
				if (!uploadfujian.exists()) {
					uploadfujian.mkdirs();
				}
				MultipartFile fj = fileList.get(0);
				String fn = fj.getOriginalFilename();
				if (null != fn && fn.length() > 0) {
					// 图片不能超过允许的大小
					if (fj.getSize() > Common.PHOTO_SIZE_ALLOW) {
						imageWeb.setSizeAllow(false);
						return imageWeb;
					} else {
						String imageFix = fn.substring(fn.lastIndexOf("."));
						String fujianpath = uploadfujian + File.separator
								+ member.getFamily() + imageFix;

						InputStream buffin = new ByteArrayInputStream(
								fj.getBytes());
						BufferedImage bi = ImageIO.read(buffin);
						if (bi != null) {
							FileOutputStream outfujian = new FileOutputStream(
									fujianpath);
							FileCopyUtils.copy(fj.getBytes(), outfujian);
							outfujian.close();
							imageWeb.setImageUrl(uploadPath + "/"
									+ member.getFamily() + imageFix);
							imageWeb.setWidth(bi.getWidth());
							imageWeb.setHeight(bi.getHeight());
							imageWeb.setSizeAllow(true);
						}

						return imageWeb;

					}

				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new AppBusinessException("upload one img failure!", e);
		}
		return null;
	}

	@Override
	public void requestSaveImage(String serverUrl, String savePath,
			String saveFilename, byte[] imageData) throws AppBusinessException {
		try {
			String ret = HttpProxy.sendImage(serverUrl, savePath, saveFilename,
					imageData);
			if (null == ret || "error".equals(ret)) {
				if (logger.isErrorEnabled()) {
					logger.error("Request save image failure!");
				}
				throw new AppBusinessException();
			}
		} catch (Exception e) {
			if (logger.isErrorEnabled()) {
				logger.error("Request save image failure!", e);
			}
			throw new AppBusinessException(e);
		}
	}

	@Override
	public void requestDeleteImage(String serverUrl, String imageFile)
			throws AppBusinessException {
		try {
			String ret = HttpProxy.deleteImage(imageServer + "", imageFile);
			if (null == ret || "error".equals(ret)) {
				if (logger.isErrorEnabled()) {
					logger.error("Request delete image failure!");
				}
				throw new AppBusinessException();
			}
		} catch (Exception e) {
			if (logger.isErrorEnabled()) {
				logger.error("Request delete image failure!", e);
			}
			throw new AppBusinessException(e);
		}
	}

	@Override
	public void requestDeleteImage(String imageFile)
			throws AppBusinessException {
		requestDeleteImage(imageServer + "deleteImage.ajax", imageFile);
	}

	@Override
	public void saveImage(InputStream in, String savePath, String saveFilename)
			throws AppBusinessException {
		try {
			String path = imageDir + File.separator + savePath + File.separator;
			File filePath = new File(path);
			if (!filePath.exists()) {
				filePath.mkdirs();
			}
			String fileName = path + saveFilename;
			BufferedImage bi = ImageIO.read(in);
			ImageIO.write(bi, "JPG", new File(fileName));
		} catch (Exception e) {
			if (logger.isErrorEnabled()) {
				logger.error("Save image failure!", e);
			}
			throw new AppBusinessException(e);
		}
	}

	@Override
	public void deleteImage(String imageFile) throws AppBusinessException {
		try {
			String fileName = imageDir + File.separator + imageFile;
			File file = new File(fileName);
			file.delete();
		} catch (Exception e) {
			if (logger.isErrorEnabled()) {
				logger.error("Delete image failure!", e);
			}
			throw new AppBusinessException(e);
		}
	}

}
